#ifndef ABCCompositor_H__
#define ABCCompositor_H__
#include <vector>

#include "CompositorTraits.cpp"	//Fixing a bug
#include "CompositorIterator.h"
using namespace std;

#define CALL_MEMBER_FN(object,ptrToMember)  ((object).*(ptrToMember))
#define CREATE_FUNCTION_POINTER(className,functionName) (&className::functionName)

//Compositor Logic Goes Here!


template <class PEA,class TRAITS = _traits<void>>
class BaseCompositor
{
	template <class PEA> friend  class CompositorFlow;
protected:
	explicit BaseCompositor(){}
	virtual ~BaseCompositor()
	{
		clear();
	}
	typedef vector<PEA*> tItemVec;
	

	tItemVec	m_ItemCol;

public:

	
	//typedef CompositorIterator<BaseCompositor>	iterator;
	
	typedef	typename tItemVec::iterator	compositorIterator;
	typedef	typename tItemVec::reverse_iterator	compositoreIteratorReverse;
	typedef	typename PEA	_PEA;
	typedef typename TRAITS	_TRAITS;

	virtual void addItem(PEA* newItem);
	void clear();

	inline typename tItemVec::size_type retItemCount() { return m_ItemCol.size(); }
	//TODO	Maybe extracting the Iterator, I wonder if I really need to expose at all...
	compositorIterator begin() { return m_ItemCol.begin(); }
	compositorIterator end() { return m_ItemCol.end(); }

	compositoreIteratorReverse rbegin() { return m_ItemCol.rbegin(); }
	compositoreIteratorReverse rend() { return m_ItemCol.rend(); }
	
};


/*

	ABCCompositor
	ABCCompositor_0Ret1ArgRef
	ABCCompositor_0Ret1ArgPtr

	ABCCompositor_1Ret0Arg
	ABCCompositor_1RetRef0Arg
	ABCCompositor_1RetPtr0Arg

	ABCCompositor_1Ret1Arg
	ABCCompositor_1RetRef1Arg
	ABCCompositor_1RetPtr1Arg

	ABCCompositor_1Ret2Arg
	ABCCompositor_1RetRef2Arg
	ABCCompositor_1RetPtr2Arg

*/

//template <class PEA,void (PEA::*funcPtr)()> class CompositorFlow<PEA,funcPtr>;
//Compositor ABC Class 0 RetVal 0 Args
template <class PEA,void (PEA::*funcPtr)(),class TRAITS = _traits<void>>
class ABCCompositor : public virtual BaseCompositor<PEA>
{
public:

	template <class PEA> friend  class CompositorFlow;
	typedef CompositorIterator<ABCCompositor>	iterator;
	typedef typename void (PEA::*functor)();
	void IterateThrough();

};

//Compositor ABC Class 0 RetVal 1 Args
template <class ARG1, class PEA,void (PEA::*funcPtr)(ARG1& Arg1),class TRAITS = _traits<void>>
class ABCCompositor_0Ret1ArgRef : public virtual BaseCompositor<PEA>
{
public:
	
	typedef CompositorIterator<ABCCompositor_0Ret1ArgRef>	iterator;
	typedef typename void (PEA::*functor)(ARG1& Arg1);
	void IterateThrough(ARG1& Arg1);
};

//Compositor ABC Class 0 RetVal 1 Args
template <class ARG1, class PEA,void (PEA::*funcPtr)(ARG1* Arg1),class TRAITS = _traits<void>>
class ABCCompositor_0Ret1ArgPtr : public virtual BaseCompositor<PEA>
{
public:
	typedef CompositorIterator<ABCCompositor_0Ret1ArgPtr>	iterator;
	typedef typename void (PEA::*functor)(ARG1* Arg1);
	void IterateThrough(ARG1* Arg1);
};

//Compositor ABC Class 1 RetVal 0 Args
template <class RET , class PEA , RET (PEA::*funcPtr)(),class TRAITS = _traits<RET>>
class ABCCompositor_1Ret0Arg : public virtual BaseCompositor<PEA>
{
public:
	typedef	typename	RET	_RET;
	typedef CompositorIterator<ABCCompositor_1Ret0Arg>	iterator;
	typedef typename RET (PEA::*functor)();
	RET IterateThrough();
};

////Compositor ABC Class 1 RetVal 0 Args
//template <class PEA , void (PEA::*funcPtr)(),class TRAITS = _traits<void>>
//class ABCCompositor_1Ret0Arg<void,class PEA , void (PEA::*funcPtr)(),class TRAITS = _traits<void>>: public virtual BaseCompositor<PEA>
//{
//public:
//	typedef	typename	void	_RET;
//	typedef CompositorIterator<ABCCompositor_1Ret0Arg>	iterator;
//	typedef typename void (PEA::*functor)();
//	RET IterateThrough();
//};


//Compositor ABC Class 1 RetValRef 0 Args
template <class RET , class PEA , RET& (PEA::*funcPtr)(),class TRAITS = _traits<RET>>
class ABCCompositor_1RetRef0Arg : public virtual BaseCompositor<PEA>
{
public:

	typedef CompositorIterator<ABCCompositor_1RetRef0Arg>	iterator;
	typedef typename RET& (PEA::*functor)();
	RET& IterateThrough();
};
//Compositor ABC Class 1 RetValPtr 0 Args
template <class RET , class PEA , RET* (PEA::*funcPtr)(),class TRAITS = _traits<RET>>
class ABCCompositor_1RetPtr0Arg : public virtual BaseCompositor<PEA>
{
public:

	typedef CompositorIterator<ABCCompositor_1RetPtr0Arg>	iterator;
	typedef typename RET* (PEA::*functor)();
	RET* IterateThrough();
};

//Compositor ABC Class 1 RetVal 1 Args
template <class RET , class ARG1, class PEA,RET (PEA::*funcPtr)(ARG1& Arg1),class TRAITS = _traits<RET>>
class ABCCompositor_1Ret1Arg : public virtual BaseCompositor<PEA>
{
public:

	typedef CompositorIterator<ABCCompositor_1Ret1Arg>	iterator;
	typedef typename RET (PEA::*functor)(ARG1& Arg1);
	RET IterateThrough(ARG1& Arg1);
};

//Compositor ABC Class 1 RetValRef 1 Args
template <class RET , class ARG1, class PEA,RET& (PEA::*funcPtr)(ARG1& Arg1),class TRAITS = _traits<RET>>
class ABCCompositor_1RetRef1Arg : public virtual BaseCompositor<PEA>
{
public:

	typedef CompositorIterator<ABCCompositor_1RetRef1Arg>	iterator;
	typedef typename RET& (PEA::*functor)(ARG1& Arg1);
	RET& IterateThrough(ARG1& Arg1);
};

//Compositor ABC Class 1 RetValPtr 1 Args
template <class RET , class ARG1, class PEA,RET* (PEA::*funcPtr)(ARG1& Arg1),class TRAITS = _traits<RET>>
class ABCCompositor_1RetPtr1Arg : public virtual BaseCompositor<PEA>
{
public:

	typedef CompositorIterator<ABCCompositor_1RetPtr1Arg>	iterator;
	typedef typename RET* (PEA::*functor)(ARG1& Arg1);
	RET* IterateThrough(ARG1& Arg1);
};

//Compositor ABC Class 1 RetVal 2 Args
template <class RET , class ARG1, class ARG2 , class PEA,RET (PEA::*funcPtr)(ARG1& Arg1 , ARG2& Arg2),class TRAITS = _traits<RET>>
class ABCCompositor_1Ret2Arg : public virtual BaseCompositor<PEA>
{
public:
	RET IterateThrough(ARG1& Arg1,ARG2& Arg2);
};

//Compositor ABC Class 1 RetValRef 2 Args
template <class RET , class ARG1, class ARG2 , class PEA,RET& (PEA::*funcPtr)(ARG1& Arg1 , ARG2& Arg2),class TRAITS = _traits<RET>>
class ABCCompositor_1RetRef2Arg : public virtual BaseCompositor<PEA>
{
public:
	RET& IterateThrough(ARG1& Arg1,ARG2& Arg2);
};

//Compositor ABC Class 1 RetValPtr 2 Args
template <class RET , class ARG1, class ARG2 , class PEA,RET* (PEA::*funcPtr)(ARG1& Arg1 , ARG2& Arg2),class TRAITS = _traits<RET>>
class ABCCompositor_1RetPtr2Arg : public virtual BaseCompositor<PEA>
{
public:
	RET* IterateThrough(ARG1& Arg1,ARG2& Arg2);
};

//DECLINED	-	TODO	ADD Factory \ Abstract Factory for compositors	=>	Abstract Factory cannot Create Pre-Processored Classes!!!
//TODO	Check to see if the support of catch try is needed
//DONE		-	TODO	Check if there's Implementation for all Compositors
//TODO	Maybe add even more Compositors
//TODO	Maybe add more variations for Compositors
//TODO	Maybe add a macro for a fast creation of Compositors...

#include "Compositor.cpp"	//Fixes Template issues... cannot link without.
#endif